<?php
/**
 *
 * Thrift Transport class
 * create and manage transport session through Thrift Api
 * @author haumv
 * @version $Id: ThriftTransport.php 5195 2012-12-18 09:33:47Z dangnh6 $
 *
 */
$GLOBALS['THRIFT_ROOT'] = ROOT_PATH . '/library/SGN/thrift';

// Load up all the thrift stuff
include_once $GLOBALS['THRIFT_ROOT'] . '/Thrift.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/protocol/TBinaryProtocol.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/transport/TSocket.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/transport/TBufferedTransport.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/transport/TFramedTransport.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/packages/sgn/sgnService.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/packages/ticker/sgnTickerService.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/packages/EsbService/EsbService.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/packages/DaspApiService/DaspJsonApi.php';
include_once $GLOBALS['THRIFT_ROOT'] . '/packages/relation/sgnRelation.php';

class SGN_ThriftTransport
{
    private $_socket = null;
    private $_transport = null;
    private $_protocol = null;
    private $_sgnServiceClient = null;
    private $_tickerServiceClient = null;
    private $_esbServiceClient = null;
    private $_sgnRelationClient = null;
    private $_daspServiceClient = null;
    private $_startTime = 0;
    /**
     * Object to help factory method
     * 
     * @var SGN_ThriftTransport
     */
    static $_localCache = null;
    public function __construct ($options, $chooser)
    {
        $trace = debug_backtrace();
        $caller = array_shift($trace);
        if ($caller['class'] != 'SGN_ThriftTransport') {
            throw new SGN_Exception('Please create calss through SGN_ThriftTransport::factory($options, $chooser) method');
        }
        if (SGN_Application::isRegistered('profiler')) {
            $this->_options = $options;
            $this->_profilerData[THRIFT] = $options;
        }
        $this->_socket = new TSocket($options['host'], $options['port'], TRUE);
        $this->_socket->setSendTimeout(100);
        $this->_socket->setRecvTimeout(100);
        $this->_transport = new TFramedTransport($this->_socket);
        $this->_protocol = new TBinaryProtocolAccelerated($this->_transport);
        if($chooser === 'sgnService'){
            $this->_sgnServiceClient = new sgn_sgnServiceClient($this->_protocol);
        } else if($chooser === 'esbService') {
            $this->_esbServiceClient = new EsbServiceClient($this->_protocol);
        } else if($chooser === 'sgnRelation') {
            $this->_sgnRelationClient = new sgnRelationClient($this->_protocol);
        } else if($chooser === 'tickerService') {
            $this->_tickerServiceClient = new sgnTickerServiceClient($this->_protocol);
        } else if($chooser === 'daspService') {
            $this->_daspServiceClient = new DaspJsonApiClient($this->_protocol);
        }
    }
    /**
     * 
     * Factory method to ensure singleton
     * 
     * @param array $options host and port of Thrift server
     * @param string
     * 
     * @return SGN_ThriftTransport
     * 
     */
    public static function factory($options, $chooser)
    {
        $selfKey = $options['host'] . '_' . $options['port'] . '_' . $chooser;
        if (self::$_localCache[$selfKey]) {
            return self::$_localCache[$selfKey];
        }
        self::$_localCache[$selfKey] = new self($options, $chooser);
        return self::$_localCache[$selfKey];
    }
    /**
     * Overwritten magical function to add profiler data
     * 
     * @param string $method
     * @param array $args
     * @return mixed
     */
    public function __call($method, $args) {
        // if first letter of method does not equal to "_"
        if ($method[0] === '_') {
            return;
        }
        $this->_startTime = microtime(true);
        $result = call_user_func_array(array($this, '_' . $method), $args);
        if (SGN_Application::isRegistered('profiler')) {
            $totalTime = sprintf("%1.3f", (microtime(true) - $this->_startTime) * 1000); // in miliseconds
            $profilerGroup = $this->_options['host'] . '_' . $this->_options['port'];
            $profilerGroup = 'THRIFT';
            $this->_profilerData['totalTime'] = $totalTime;
            $this->_profilerData['method'] = $method;
            $this->_profilerData['args'] = $args;
            SGN_Application::get('profiler')->setProfilerData('THRIFT', $this->_profilerData);
        } else {
//             ChromePhp::log('else'  . $method . ' ' . implode(', ', $args));
        }
        return $result;
    }
    /* functions for sgnService */
    public function _registerAccount ($accountId)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->registerAccount($accountId);
    }
    public function _getAccount ($accountId)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->getAccount($accountId);
    }
    public function _unRegisterAccount ($accountId)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->unRegisterAccount($accountId);
    }
    public function _createRelationship ($accountId1, $accountId2, $rtype)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->createRelationship($accountId1, $accountId2, $rtype);
    }
    public function _removeRelationship ($accountId1, $accountId2, $rtype)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->removeRelationship($accountId1, $accountId2, $rtype);
    }
    public function _pushFeed ($accountId, $message, $rtype)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->pushFeed($accountId, $message, $rtype);
    }
    public function _getMyFeed ($accountId, $pageNume, $pageSize)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->getMyFeed($accountId, $pageNume, $pageSize);
    }
    public function _getMyWallFeed ($accountId, $pageNume, $pageSize)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->getMyWallFeed($accountId, $pageNume, $pageSize);
    }
    public function _getFeeds($feedIds)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->getFeeds($feedIds);
    }
    public function _getFeed($feedId)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->getFeed($feedId);
    }
    public function _like($feedId)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->like($feedId);
    }
    public function _unlike($feedId)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->unlike($feedId);
    }
    public function _comment($feedId)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->comment($feedId);
    }
    public function _uncomment($feedId)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->uncomment($feedId);
    }
    public function _share($feedId)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->share($feedId);
    }
    public function _unshare($feedId)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->unshare($feedId);
    }
    public function _getPublicFeeds($pageNum, $pageSize)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->getPublicFeeds($pageNum, $pageSize);
    }
    public function _getNextFeeds($accountId, $feedid, $pageSize)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->getNextFeeds($accountId, $feedid, $pageSize);
    }
    public function _getNextWallFeeds($accountId, $feedid, $pageSize)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->getNextWallFeeds($accountId, $feedid, $pageSize);
    }
    public function _getNextPublicFeeds($feedid, $pageSize)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->getNextPublicFeeds($feedid, $pageSize);
    }
    public function _getTargetNextFeeds($targetId, $targetType, $feedId, $pageSize)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->getTargetNextFeeds($targetId, $targetType, $feedId, $pageSize);
    }
    public function _removeFeed($feedId, $targetId, $targetType = null)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->removeFeed($feedId, $targetId, $targetType);
    }
    public function _deleteFeed($feedId, $targetId, $targetType = null)
    {
        if($this->_sgnServiceClient === null)return;
        $this->_openTransport();
        return $this->_sgnServiceClient->deleteFeed($feedId, $targetId, $targetType);
    }
    /* function for ticker service*/ 
    public function _getTicker($tickerId)
    {
        if($this->_tickerServiceClient === null)return;
        $this->_openTransport();
        return $this->_tickerServiceClient->getTicker($tickerId);
    }
    public function _getNextTickers($tickerId, $userId, $pageSize)
    {
        if($this->_tickerServiceClient === null)return;
        $this->_openTransport();
        return $this->_tickerServiceClient->getNextTickers($tickerId, $userId, $pageSize);
    }
    public function _getNextTickersByProduct($tickerId, $productId, $pageSize)
    {
        if($this->_tickerServiceClient === null)return;
        $this->_openTransport();
        return $this->_tickerServiceClient->getNextTickersByProduct($tickerId, $productId, $pageSize);
    }
    public function _pushTicker($ticker)
    {
        if($this->_tickerServiceClient === null)return;
        $this->_openTransport();
        return $this->_tickerServiceClient->pushTicker($ticker);
    }
    /* functions for esbService */
    public function _requestFunction($functionName, $encodedInput, $authKey)
    {
        if($this->_esbServiceClient === null)return;
        $this->_openTransport();
        return $this->_esbServiceClient->requestFunction($functionName, $encodedInput, $authKey);
    }
    /* functions for sgnRelation */
    public function _registerUser($userId)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->registerUser($userId);
    }
    public function _checkUser($userId)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->checkUser($userId);
    }
    public function _addGroup($userId, $groupName)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->addGroup($userId, $groupName);
    }
    public function _getGroups($userId)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->getGroups($userId);
    }
    public function _getGroupByName($userId, $groupName)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->getGroupByName($userId, $groupName);
    }
    public function _removeGroup($userId, $groupId)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->removeGroup($userId, $groupId);
    }
    public function _renameGroup($userId, $groupId, $newGroupName)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->renameGroup($userId, $groupId, $newGroupName);
    }
    public function _addFriend($userId, $friendId, $groupId)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->addFriend($userId, $friendId, $groupId);
    }
    public function _getFriends($userId, $groupId)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->getFriends($userId, $groupId);
    }
    public function _checkFriend($userId, $friendId, $groupId)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->checkFriend($userId, $friendId, $groupId);
    }
    public function _removeFriend($userId, $friendId, $groupId)
    {
    	if($this->_sgnRelationClient === null)return;
    	$this->_openTransport();
    	return $this->_sgnRelationClient->removeFriend($userId, $friendId, $groupId);
    }
    /* Dasp service */
    public function _callApi($moduleName, $functionName, $jsonEncodedInput, $authKey)
    {
        if($this->_daspServiceClient === null)return;
        $this->_openTransport();
        return $this->_daspServiceClient->callApi($moduleName, $functionName, $jsonEncodedInput, $authKey);
    }
    
    /* common function */
    private function _openTransport ()
    {
        if (! $this->_transport->isOpen()) {
            $this->_transport->open();
        }
    }
    public function __destruct ()
    {
        if ($this->_transport->isOpen()) {
            $this->_transport->close();
        }
    }
}